
#ifndef __CRYPTECHAIN_H
#define __CRYPTECHAIN_H

#include <stdint.h>
#include "../iface/CryptInterface.h"
#include "../aprtools/APRBucketBrigade.h"
#include "../iface/debug.h"
#include "KeyPair.h"

#include "keys.h"

#define CRYPTCONTEXT_USED                     0x00
#define CRYPTCONTEXT_PUBLIC_KEY_ENCRYPT       0x01
#define CRYPTCONTEXT_PRIVATE_KEY_DECRYPT      0x02
#define CRYPTCONTEXT_SIGN_PRIVATE_KEY         0x03
#define CRYPTCONTEXT_CHECKSIG_PUBLIC_KEY      0x04
#define CRYPTCONTEXT_COMPRESS                 0x05
#define CRYPTCONTEXT_DECOMPRESS               0x06
#define CRYPTCONTEXT_SYMM_KEY_ENCRYPT         0x07
#define CRYPTCONTEXT_SYMM_KEY_DECRYPT         0x08
#define CRYPTCONTEXT_DONEINTERJECTION         0x10

// This was 65536
#define ENV_READ_BUFFER 1114112

//#define DEBUG_CRYPTLIB_OBJECTS 1

typedef struct crypt_envelope_link
{
   CRYPT_ENVELOPE envelope;
   CRYPT_CONTEXT cntxt;
   int intent;
   struct crypt_envelope_link *inward;
   struct crypt_envelope_link *outward;
   int bytesinbuf;
   char *buf;
   char *bufl;
} CryptELink;

class CryptEChain
{
   public:
      int PrePushInterjection(CryptELink *clink);
      int PostFlushInterjection(CryptELink *clink);
      int PrePopInterjection(CryptELink *clink);
      CryptEChain();
      ~CryptEChain();
      int64_t ProcessIteration(APRBucketBrigade *inp, char *dbuffer, int imaxdata);
      int ProcessIteration(APRBucketBrigade *inp, APRBucketBrigade *out);
      void Process(APRBucketBrigade *inp, APRBucketBrigade *out);
      void AddEnvelope(CRYPT_ENVELOPE nenvelope, CRYPT_CONTEXT icntxt, int iintent);
      static CRYPT_ENVELOPE EncodingEnvelope();
      static CRYPT_ENVELOPE DecodingEnvelope();
      static CRYPT_ENVELOPE GenerateCompressEnv();
      static CRYPT_ENVELOPE GenerateDecompressEnv();
      void BuildBasicChain(const char *cname, const char *sname, KeyPair *crypto, KeyPair *signing, int dodecrypt, int docompress);
      void BuildBasicChain2(const char *cname, const char *sname, KeyPair *crypto, KeyPair *signing, int dodecrypt, int docompress, int inputsize);
      void BuildEncryptionChain2(EncryptionKey *crypto, SigningKey *signing, int docompress, int inputsize);
      void BuildDecryptionChain2(DecryptionKey *crypto, CheckingKey *signing, int dodecompress, int inputsize);
      int IsTrusted() { return trusted; }
   private:
      CryptELink *root;
      char *firstbuf;
      int firstbib;
      int trusted;
};

#endif
